<?php

if (!defined('ADODB_DIR'))
    die();

class ADODB_sybase extends ADOConnection {

    var $databaseType = "sybase";
    var $dataProvider = 'sybase';
    var $replaceQuote = "''";
    var $fmtDate = "'Y-m-d'";
    var $fmtTimeStamp = "'Y-m-d H:i:s'";
    var $hasInsertID = true;
    var $hasAffectedRows = true;
    var $metaTablesSQL = "select name from sysobjects where type='U' or type='V'";
    var $metaColumnsSQL = "SELECT c.column_name, c.column_type, c.width FROM syscolumn c, systable t WHERE t.table_name='%s' AND c.table_id=t.table_id AND t.table_type='BASE'";
    var $concat_operator = '+';
    var $arrayClass = 'ADORecordSet_array_sybase';
    var $sysDate = 'GetDate()';
    var $leftOuter = '*=';
    var $rightOuter = '=*';

    function ADODB_sybase() {
        
    }

    function _insertid() {
        return $this->GetOne('select @@identity');
    }

    function _affectedrows() {
        return $this->GetOne('select @@rowcount');
    }

    function BeginTrans() {

        if ($this->transOff)
            return true;
        $this->transCnt += 1;

        $this->Execute('BEGIN TRAN');
        return true;
    }

    function CommitTrans($ok = true) {
        if ($this->transOff)
            return true;

        if (!$ok)
            return $this->RollbackTrans();

        $this->transCnt -= 1;
        $this->Execute('COMMIT TRAN');
        return true;
    }

    function RollbackTrans() {
        if ($this->transOff)
            return true;
        $this->transCnt -= 1;
        $this->Execute('ROLLBACK TRAN');
        return true;
    }

    function RowLock($tables, $where, $col = 'top 1 null as ignore') {
        if (!$this->_hastrans)
            $this->BeginTrans();
        $tables = str_replace(',', ' HOLDLOCK,', $tables);
        return $this->GetOne("select $col from $tables HOLDLOCK where $where");
    }

    function SelectDB($dbName) {
        $this->database = $dbName;
        $this->databaseName = $dbName;
        if ($this->_connectionID) {
            return @sybase_select_db($dbName);
        } else
            return false;
    }

    function ErrorMsg() {
        if ($this->_logsql)
            return $this->_errorMsg;
        if (function_exists('sybase_get_last_message'))
            $this->_errorMsg = sybase_get_last_message();
        else
            $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : 'SYBASE error messages not supported on this platform';
        return $this->_errorMsg;
    }

    function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) {
        if (!function_exists('sybase_connect'))
            return null;

        if ($this->charSet) {
            $this->_connectionID = sybase_connect($argHostname, $argUsername, $argPassword, $this->charSet);
        } else {
            $this->_connectionID = sybase_connect($argHostname, $argUsername, $argPassword);
        }

        $this->_connectionID = sybase_connect($argHostname, $argUsername, $argPassword);
        if ($this->_connectionID === false)
            return false;
        if ($argDatabasename)
            return $this->SelectDB($argDatabasename);
        return true;
    }

    function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) {
        if (!function_exists('sybase_connect'))
            return null;

        if ($this->charSet) {
            $this->_connectionID = sybase_pconnect($argHostname, $argUsername, $argPassword, $this->charSet);
        } else {
            $this->_connectionID = sybase_pconnect($argHostname, $argUsername, $argPassword);
        }
        if ($this->_connectionID === false)
            return false;
        if ($argDatabasename)
            return $this->SelectDB($argDatabasename);
        return true;
    }

    function _query($sql, $inputarr = false) {
        global $ADODB_COUNTRECS;

        if ($ADODB_COUNTRECS == false && ADODB_PHPVER >= 0x4300)
            return sybase_unbuffered_query($sql, $this->_connectionID);
        else
            return sybase_query($sql, $this->_connectionID);
    }

    function SelectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0) {
        if ($secs2cache > 0) {
            $rs = ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
            return $rs;
        }

        $nrows = (integer) $nrows;
        $offset = (integer) $offset;

        $cnt = ($nrows >= 0) ? $nrows : 999999999;
        if ($offset > 0 && $cnt)
            $cnt += $offset;

        $this->Execute("set rowcount $cnt");
        $rs = ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, 0);
        $this->Execute("set rowcount 0");

        return $rs;
    }

    function _close() {
        return @sybase_close($this->_connectionID);
    }

    static function UnixDate($v) {
        return ADORecordSet_array_sybase::UnixDate($v);
    }

    static function UnixTimeStamp($v) {
        return ADORecordSet_array_sybase::UnixTimeStamp($v);
    }

    function SQLDate($fmt, $col = false) {
        if (!$col)
            $col = $this->sysTimeStamp;
        $s = '';

        $len = strlen($fmt);
        for ($i = 0; $i < $len; $i++) {
            if ($s)
                $s .= '+';
            $ch = $fmt[$i];
            switch ($ch) {
                case 'Y':
                case 'y':
                    $s .= "datename(yy,$col)";
                    break;
                case 'M':
                    $s .= "convert(char(3),$col,0)";
                    break;
                case 'm':
                    $s .= "str_replace(str(month($col),2),' ','0')";
                    break;
                case 'Q':
                case 'q':
                    $s .= "datename(qq,$col)";
                    break;
                case 'D':
                case 'd':
                    $s .= "str_replace(str(datepart(dd,$col),2),' ','0')";
                    break;
                case 'h':
                    $s .= "substring(convert(char(14),$col,0),13,2)";
                    break;

                case 'H':
                    $s .= "str_replace(str(datepart(hh,$col),2),' ','0')";
                    break;

                case 'i':
                    $s .= "str_replace(str(datepart(mi,$col),2),' ','0')";
                    break;
                case 's':
                    $s .= "str_replace(str(datepart(ss,$col),2),' ','0')";
                    break;
                case 'a':
                case 'A':
                    $s .= "substring(convert(char(19),$col,0),18,2)";
                    break;

                default:
                    if ($ch == '\\') {
                        $i++;
                        $ch = substr($fmt, $i, 1);
                    }
                    $s .= $this->qstr($ch);
                    break;
            }
        }
        return $s;
    }

    function MetaPrimaryKeys($table) {
        $sql = "SELECT c.column_name " .
                "FROM syscolumn c, systable t " .
                "WHERE t.table_name='$table' AND c.table_id=t.table_id " .
                "AND t.table_type='BASE' " .
                "AND c.pkey = 'Y' " .
                "ORDER BY c.column_id";

        $a = $this->GetCol($sql);
        if ($a && sizeof($a) > 0)
            return $a;
        return false;
    }

}

global $ADODB_sybase_mths;
$ADODB_sybase_mths = array(
    'JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4, 'MAY' => 5, 'JUN' => 6,
    'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' => 10, 'NOV' => 11, 'DEC' => 12);

class ADORecordset_sybase extends ADORecordSet {

    var $databaseType = "sybase";
    var $canSeek = true;
    var $_mths = array('JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4, 'MAY' => 5, 'JUN' => 6, 'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' => 10, 'NOV' => 11, 'DEC' => 12);

    function ADORecordset_sybase($id, $mode = false) {
        if ($mode === false) {
            global $ADODB_FETCH_MODE;
            $mode = $ADODB_FETCH_MODE;
        }
        if (!$mode)
            $this->fetchMode = ADODB_FETCH_ASSOC;
        else
            $this->fetchMode = $mode;
        $this->ADORecordSet($id, $mode);
    }

    function FetchField($fieldOffset = -1) {
        if ($fieldOffset != -1) {
            $o = @sybase_fetch_field($this->_queryID, $fieldOffset);
        } else if ($fieldOffset == -1) {
            $o = @sybase_fetch_field($this->_queryID);
        }
        if ($o && !isset($o->type))
            $o->type = ($o->numeric) ? 'float' : 'varchar';
        return $o;
    }

    function _initrs() {
        global $ADODB_COUNTRECS;
        $this->_numOfRows = ($ADODB_COUNTRECS) ? @sybase_num_rows($this->_queryID) : -1;
        $this->_numOfFields = @sybase_num_fields($this->_queryID);
    }

    function _seek($row) {
        return @sybase_data_seek($this->_queryID, $row);
    }

    function _fetch($ignore_fields = false) {
        if ($this->fetchMode == ADODB_FETCH_NUM) {
            $this->fields = @sybase_fetch_row($this->_queryID);
        } else if ($this->fetchMode == ADODB_FETCH_ASSOC) {
            $this->fields = @sybase_fetch_row($this->_queryID);
            if (is_array($this->fields)) {
                $this->fields = $this->GetRowAssoc(ADODB_ASSOC_CASE);
                return true;
            }
            return false;
        } else {
            $this->fields = @sybase_fetch_array($this->_queryID);
        }
        if (is_array($this->fields)) {
            return true;
        }

        return false;
    }

    function _close() {
        return @sybase_free_result($this->_queryID);
    }

    static function UnixDate($v) {
        return ADORecordSet_array_sybase::UnixDate($v);
    }

    static function UnixTimeStamp($v) {
        return ADORecordSet_array_sybase::UnixTimeStamp($v);
    }

}

class ADORecordSet_array_sybase extends ADORecordSet_array {

    function ADORecordSet_array_sybase($id = -1) {
        $this->ADORecordSet_array($id);
    }

    static function UnixDate($v) {
        global $ADODB_sybase_mths;
        if (!preg_match("/([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})/"
                        , $v, $rr))
            return parent::UnixDate($v);

        if ($rr[3] <= TIMESTAMP_FIRST_YEAR)
            return 0;

        $themth = substr(strtoupper($rr[1]), 0, 3);
        $themth = $ADODB_sybase_mths[$themth];
        if ($themth <= 0)
            return false;
        return adodb_mktime(0, 0, 0, $themth, $rr[2], $rr[3]);
    }

    static function UnixTimeStamp($v) {
        global $ADODB_sybase_mths;
        if (!preg_match("/([A-Za-z]{3})[-/\. ]([0-9 ]{1,2})[-/\. ]([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})/"
                        , $v, $rr))
            return parent::UnixTimeStamp($v);
        if ($rr[3] <= TIMESTAMP_FIRST_YEAR)
            return 0;

        $themth = substr(strtoupper($rr[1]), 0, 3);
        $themth = $ADODB_sybase_mths[$themth];
        if ($themth <= 0)
            return false;

        switch (strtoupper($rr[6])) {
            case 'P':
                if ($rr[4] < 12)
                    $rr[4] += 12;
                break;
            case 'A':
                if ($rr[4] == 12)
                    $rr[4] = 0;
                break;
            default:
                break;
        }
        return adodb_mktime($rr[4], $rr[5], 0, $themth, $rr[2], $rr[3]);
    }

}

?>
